package com.lemon.cloud.oauth.support.mp;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.lemon.cloud.oauth.support.base.OAuth2ResourceOwnerBaseAuthenticationProvider;
import com.lemon.cloud.security.enums.GrantTypeEnum;
import com.lemon.cloud.security.enums.WeChatMpCodeParams;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
import org.springframework.security.oauth2.core.OAuth2Token;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;

import java.util.Map;

/**
 * @author huangds
 * @description 处理用户名密码授权
 */
@Slf4j
public class OAuth2ResourceOwnerMpAuthenticationProvider
		extends OAuth2ResourceOwnerBaseAuthenticationProvider<OAuth2ResourceOwnerMpAuthenticationToken> {

	/**
	 * The plaintext password used to perform PasswordEncoder#matches(CharSequence,
	 * String)} on when the user is not found to avoid SEC-2056.
	 */
	private static final String USER_NOT_FOUND_PASSWORD = "userNotFoundPassword";


	public OAuth2ResourceOwnerMpAuthenticationProvider(AuthenticationManager authenticationManager,
                                                             OAuth2AuthorizationService authorizationService,
                                                             OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator) {
		super(authenticationManager, authorizationService, tokenGenerator);
	}

	@Override
	public UsernamePasswordAuthenticationToken buildToken(Map<String, Object> reqParameters) {
		String code = (String) reqParameters.getOrDefault(WeChatMpCodeParams.CODE, StrUtil.EMPTY);
		String appId = (String) reqParameters.getOrDefault(WeChatMpCodeParams.APPID, StrUtil.EMPTY);
		String state = (String) reqParameters.getOrDefault(WeChatMpCodeParams.STATE, StrUtil.EMPTY);
		JSONObject json = new JSONObject();
		json.put(WeChatMpCodeParams.CODE,code);
		json.put(WeChatMpCodeParams.APPID,appId);
		json.put(WeChatMpCodeParams.STATE,state);
		return new UsernamePasswordAuthenticationToken(json.toJSONString(), null);
	}

	@Override
	public boolean supports(Class<?> authentication) {
		boolean supports = OAuth2ResourceOwnerMpAuthenticationToken.class.isAssignableFrom(authentication);
		log.debug("supports authentication=" + authentication + " returning " + supports);
		return supports;
	}

	@Override
	public void checkClient(RegisteredClient registeredClient) {
		assert registeredClient != null;
		if (!registeredClient.getAuthorizationGrantTypes().contains(new AuthorizationGrantType(GrantTypeEnum.WECHAT_MP_CODE.getType()))) {
			throw new OAuth2AuthenticationException(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT);
		}
	}
}
